package com.club.uni.service;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.club.uni.dto.PushUniDoing;
import com.club.uni.utils.RRException;
import com.getui.push.v2.sdk.api.UserApi;
import com.getui.push.v2.sdk.common.ApiResult;
import com.getui.push.v2.sdk.dto.req.Audience;
import com.getui.push.v2.sdk.dto.req.Settings;
import com.getui.push.v2.sdk.dto.req.Strategy;
import com.getui.push.v2.sdk.dto.req.message.PushChannel;
import com.getui.push.v2.sdk.dto.req.message.PushDTO;
import com.getui.push.v2.sdk.dto.req.message.PushMessage;
import com.getui.push.v2.sdk.dto.req.message.android.AndroidDTO;
import com.getui.push.v2.sdk.dto.req.message.android.GTNotification;
import com.getui.push.v2.sdk.dto.req.message.android.ThirdNotification;
import com.getui.push.v2.sdk.dto.req.message.android.Ups;
import com.getui.push.v2.sdk.dto.req.message.ios.Alert;
import com.getui.push.v2.sdk.dto.req.message.ios.Aps;
import com.getui.push.v2.sdk.dto.req.message.ios.IosDTO;
import com.getui.push.v2.sdk.dto.res.CidStatusDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @Author: wxj
 * @Date: 2021-04-28 16:04
 */
@Service
@Slf4j
public class PushService {


    public Map<String, Object> push(PushUniDoing push){
        Map<String, Object> map=new HashMap<>();
        Boolean userOnline = getUserOnline(push.getUserApi(),push.getCid());
        if (ObjectUtil.isNull(userOnline)){
            throw new RRException("请求个推服务器发送错误");
        }
        if (userOnline){ //在线就用个推
            map= gtPush(push);
        }else { //不在线就用厂商推
            map=  BusinessPush(push);
        }
        return map;
    }

    /***
     * 查看用户状态
     * online在线
     * offline离线
     * @param cid
     * @return
     */
    public Boolean getUserOnline(UserApi userApi, String cid){
        Set<String> cids = new HashSet<String>();
        cids.add(cid);
        // 查询用户状态
        ApiResult<Map<String, CidStatusDTO>> apiResult = userApi.queryUserStatus(cids);
        if (apiResult.isSuccess()) {
            Map<String, CidStatusDTO> data = apiResult.getData();
            CidStatusDTO cidStatusDTO = data.get(cid);
            log.error("当前cid:{}查询在线状态",cidStatusDTO.getStatus());
            return cidStatusDTO.getStatus().equals("online")?true:false;
        }
        log.error("当前cid:{}查询在线状态出现错误 ,code:{},msg:",cid,apiResult.getCode(),apiResult.getMsg());
        return  null;
    }

    /***
     * 厂商推送
     * @param pushUni
     */
    public Map<String, Object> BusinessPush(PushUniDoing pushUni){
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("path",pushUni.getPath());
        //根据cid进行单推
        PushDTO<Audience> pushDTO = new PushDTO<Audience>();
        // 设置推送参数
        pushDTO.setRequestId(System.currentTimeMillis() + "");//requestid需要每次变化唯一
        //配置推送条件
        /****
         *
         * 1: 表示该消息在用户在线时推送个推通道，用户离线时推送厂商通道;
         * 2: 表示该消息只通过厂商通道策略下发，不考虑用户是否在线;
         * 3: 表示该消息只通过个推通道下发，不考虑用户是否在线；
         * 4: 表示该消息优先从厂商通道下发，若消息内容在厂商通道代发失败后会从个推通道下发。
         *
         */
        Strategy strategy=new Strategy();
        strategy.setDef(1);
        /**
         * ios通道策略1-4，表示含义同上，要推送ios通道，需要在个推开发者中心上传ios证书，建议填写2或4，否则可能会有消息不展示的问题
         */
        strategy.setIos(4);
        Settings settings=new Settings();
        settings.setStrategy(strategy);
        pushDTO.setSettings(settings);
        settings.setTtl(3600000);//消息有效期，走厂商消息需要设置该值
        PushChannel pushChannel = new PushChannel();
        if (pushUni.getClientType()==1){
            //推送苹果离线通知标题内容
            Alert alert=new Alert();
            alert.setTitle(pushUni.getTitle());
            alert.setBody(pushUni.getContent());
            Aps aps = new Aps();
            //1表示静默推送(无通知栏消息)，静默推送时不需要填写其他参数。
            //苹果建议1小时最多推送3条静默消息
            aps.setContentAvailable(0);
            aps.setSound("default");
            aps.setAlert(alert);
            IosDTO iosDTO = new IosDTO();
            iosDTO.setPayload(JSON.toJSONString(jsonObject));
            iosDTO.setAps(aps);
            iosDTO.setType("notify");
            pushChannel.setIos(iosDTO);
        }else {
            AndroidDTO androidDTO = new AndroidDTO();
            Ups ups = new Ups();
            ThirdNotification notification1 = new ThirdNotification();;
            ups.setNotification(notification1);
            notification1.setTitle(pushUni.getTitle());
            notification1.setBody(pushUni.getContent());
            notification1.setClickType("intent");
            notification1.setIntent("intent:#Intent;action=android.intent.action.oppopush;launchFlags=0x14000000;"
                    +"component=" +pushUni.getPackageName() +"/io.dcloud.PandoraEntry;S.UP-OL-SU=true;S.title="+pushUni.getTitle()
                    +";S.content="+pushUni.getContent()
                    +";S.payload="+ JSON.toJSONString(jsonObject)
                    +";end");
            //各厂商自有功能单项设置
            ups.addOption("HW", "/message/android/notification/badge/class", "io.dcloud.PandoraEntry");
            ups.addOption("HW", "/message/android/notification/badge/add_num", 1);
            ups.addOption("HW", "/message/android/notification/importance", "HIGH");
            ups.addOption("VV","classification",1);
            androidDTO.setUps(ups);
            pushChannel.setAndroid(androidDTO);
        }
        pushDTO.setPushChannel(pushChannel);
        // PushMessage在线走个推通道才会起作用的消息体
        PushMessage pushMessage = new PushMessage();
        pushDTO.setPushMessage(pushMessage);
        pushMessage.setTransmission(JSON.toJSONString(jsonObject));
        // 设置接收人信息
        Audience audience = new Audience();
        pushDTO.setAudience(audience);
        audience.addCid(pushUni.getCid());
        // 进行cid单推
        ApiResult<Map<String, Map<String, String>>> apiResult = pushUni.getPushApi().pushToSingleByCid(pushDTO);
        return getMapValue(apiResult,pushUni.getCid());
    }

    /***
     * 个推消息推送
     * @param pushUni
     * @return
     */
    public  Map<String, Object>  gtPush(PushUniDoing pushUni){
        PushDTO<Audience> pushDTO = new PushDTO<Audience>();
        // 设置推送参数
        pushDTO.setRequestId(System.currentTimeMillis() + "");
        PushMessage pushMessage = new PushMessage();
        pushDTO.setPushMessage(pushMessage);
        GTNotification notification = new GTNotification();
        pushMessage.setNotification(notification);
        notification.setTitle(pushUni.getTitle());
        notification.setBody(pushUni.getContent());
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("path",pushUni.getPath());
        notification.setClickType("payload");
        jsonObject.put("showTitle", pushUni.getTitle());
        jsonObject.put("showContent", pushUni.getContent());
        notification.setPayload(JSON.toJSONString(jsonObject));
        Audience audience = new Audience();
        pushDTO.setAudience(audience);
        audience.addCid(pushUni.getCid());
        // 进行cid单推
        ApiResult<Map<String, Map<String, String>>> apiResult = pushUni.getPushApi().pushToSingleByCid(pushDTO);
        return  getMapValue(apiResult,pushUni.getCid());
    }

    /***
     * 返回结果进行封装
     * @param apiResult
     * @param cid
     * @return
     */
    private Map<String, Object> getMapValue(ApiResult<Map<String, Map<String, String>>> apiResult,String cid){
        Map<String, Object> map = MapUtil.newHashMap();
        if (apiResult.isSuccess()) {
            Map<String, Map<String, String>> data = apiResult.getData();
            Optional<Map.Entry<String, Map<String, String>>> first = data.entrySet().stream().findFirst();
            Map.Entry<String, Map<String, String>> stringMapEntry = first.get();
            Map<String, String> value = stringMapEntry.getValue();
            String result = value.get(cid);
            map.put("code",200);
            map.put("result",result);
        } else {
            map.put("code",apiResult.getCode());
            map.put("result",apiResult.getMsg());
        }
        return map;
    }

}
